﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using Vowei.Core.Models;

namespace Vowei.Core.Models
{
    /// <summary>
    /// 系统中所有的任务相关，与人相关的行为，都是一个Ticket
    /// 
    /// 例如，一个任务是一个Ticket, 一个会议邀请是一个Ticket，只要这个事情需要有人参加，
    /// 那么，就应该发一个Ticket给这个人。
    /// </summary>
    [DataContract]
    public class Ticket : INamedTable, ISupportDefaultProperties, ITagable, ICommentable, IStatus, IScoped
    {
        public Ticket()
        {
            ID = Guid.NewGuid();
            ClosedDate = null;
            Comments = new List<Comment>();
            this.FillDefaultProperties();
        }

        /// <summary>
        /// Ticket的详细说明
        /// </summary>
        [DataMember]
        [Display(Name="说明")]
        public string Description { get; set; }

        /// <summary>
        /// Ticket创建的日期
        /// </summary>
        [DataMember]
        [Display(Name="创建日期")]
        public DateTime OpenDate { get; set; }

        /// <summary>
        /// Ticket关闭的日期
        /// </summary>
        /// <remarks>
        /// 这个是一个Nullable类型，如果ClosedDate为空，说明这个Ticket还没有关闭
        /// 或者就是根本没有关闭日期的，例如一个消防系统，是不应该有关闭日期的
        /// </remarks>
        [DataMember]
        [Display(Name="关闭日期")]
        public DateTime? ClosedDate { get; set; }

        /// <summary>
        /// 打开Ticket的用户，必须是用户的email
        /// </summary>
        /// <remarks>
        /// 之所以使用email来做Ticket与用户系统的外键联系，主要是考虑到：
        /// 
        /// 1、有可能开这个Ticket的用户没有在系统中注册，例如一个使用开源软件的用户，
        /// 发现了一个bug，他可以开一个bug，但我们并不要求他在系统中有注册用户。
        /// 2、这样可以整合其他的系统，例如可以跟MSN、facebook等系统的用户联系
        /// MSN Messenger自己就是用email做用户名，对于facebook, qq之类的非email格式的
        /// 用户名，我们可以采取[user@siteurl]的形式实现，例如1234567@qq.com。
        /// </remarks>
        [Display(Name="创建人")]
        public string Reporter { get; set; }

        /// <summary>
        /// Ticket指派给谁
        /// </summary>
        [DataMember]
        [Display(Name="负责人")]
        public string AssignedTo { get; set; }
        

        /// <summary>
        /// Ticket最后修改的日期
        /// </summary>
        [Required]
        [Display(Name = "上次修改日期")]
        public DateTime LastModified { get; set; }

        [Display(Name = "评论")]
        // public virtual List<Comment> Comments { get; private set; }
        public virtual List<Comment> Comments { get; set; }
                        
        #region ITagable Members

        /// <summary>
        /// 以分号分隔的标签
        /// </summary>
        [DataMember]
        [Display(Name = "标签")]
        public string TagText
        {
            get;
            set;
        }

        #endregion

        [DataMember]
        public Guid ID
        {
            get;
            set;
        }

        [DataMember]
        [Display(Name = "标题")]
        public string Title
        {
            get;
            set;
        }

        [DataMember]
        [Display(Name = "最后修改人")]
        public string LastModifiedBy
        {
            get;
            set;
        }

        [DataMember]
        [Display(Name = "% 完成百分比")]
        public float Progress { get; set; }

        [DataMember]
        [Display(Name = "优先级")]
        public string Priority { get; set; }

        [DataMember]
        [Display(Name = "状态")]
        public string Status { get; set; }

        public void ReActive()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 该Ticket需要在哪一个Milestone完成?
        /// </summary>
        /// <remarks>
        /// 如果值为null,则说明这个Ticket不属于任何一个Milestone的关键任务
        /// </remarks>

        [DataMember]
        [Display(Name = "在指定的里程碑内完成")]
        public Milestone BelongsToMilestone
        {
            get;
            set;
        }

        public Guid? BelongsToMilestoneId { get; set; }
        
        public Guid? ParentId { get; set; }
    }

    /// <summary>
    /// 代表一个软件缺陷，需要人去修复
    /// </summary>
    public class Bug : Ticket
    {
        [Display(Name = "重现步骤")]
        public string ReproStep { get; set; }
    }
        
    /// <summary>
    /// 代表时间管理里面的任务分类
    /// </summary>
    public class TaskCategory : INamedTable
    {
        public static readonly Guid ImportantUrgent = Guid.NewGuid();
        public static readonly Guid ImportantYetNotUrgent = Guid.NewGuid();
        public static readonly Guid UrgentYetNotImportant = Guid.NewGuid();
        public static readonly Guid NotImportantNotUrgent = Guid.NewGuid();

        public Guid ID { get; set; }

        [Required]
        public string Title { get; set; }
    }

    /// <summary>
    /// 用户可以将自己的工作任务类型与<seealso cref="TaskCategory"/>对应起来
    /// </summary>
    /// <remarks>
    /// 例如一个用户可以创建这样一个Category:老板的事情，然后将TaskCategory指定为ImportantUrgent，
    /// 因为他认为老板的事情永远都是紧急且重要的。
    /// 
    /// 之所以这样做，是为了帮助用户在接到新任务的时候，能够快速地明确自己的工作优先级
    /// </remarks>
    public class Category : INamedTable
    {
        public Category()
        {
            ID = Guid.NewGuid();
        }

        /// <summary>
        /// 主键
        /// </summary>
        public Guid ID { get; set; }

        /// <summary>
        /// 用户自定义的工作任务类型
        /// </summary>
        [Display(Name="种类名称")]
        public string Title { get; set; }

        /// <summary>
        /// 映射到时间管理中的任务优先级。
        /// </summary>
        [Display(Name="优先级")]
        public TaskCategory TaskCategory { get; set; }
    }
}